import json
import re
from datetime import datetime

import happybase
import pymysql
import scrapy
import uuid


class ZhihuSpiderSpider(scrapy.Spider):
    name = "zhihuSpider"
    url = 'https://gj.topsocial.com.cn/api/hot_search/getList'

    headers = {
        'Accept': 'application/json, text/plain, */*',
        'Accept-Encoding': 'gzip, deflate, br, zstd',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
        'Authorization2': 'S3NYT01ONzdITC9tbGRnY0k3d3hISDQvQUpxQ2RDUW1lc3p3TVBZVndlVT0=',
        'Content-Type': 'application/json',
        'Cookie': 'PHPSESSID=09546b737037d17420aad79f7a6b2bf3',
        'Origin': 'https://gj.topsocial.com.cn',
        'Referer': 'https://gj.topsocial.com.cn/search/hot/index',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0'
    }

    def start_requests(self):
        """
        生成初始的请求对象，这些请求将用于启动爬虫的数据抓取过程。
        使用 POST 方法发送包含分页信息的 JSON 数据到指定的 URL。
        :return: 一个生成器，产生 Scrapy 的 FormRequest 对象
        """
        for i in range(1, 5):
            data = {
                "page": i,
                "limit": 10,
                "forms": {
                    "search_keyword": "",
                    "start_time": "",
                    "end_time": "",
                    "platform": "zhihu",
                    "type": "0"
                }
            }

            yield scrapy.FormRequest(url=self.url, method='POST', body=json.dumps(data), headers=self.headers,
                                     callback=self.parse)

    def parse(self, response):
        """
        该函数用于处理响应数据
        :param response: 响应状态码
        :return: 无返回值
        """
        # 处理响应数据
        if response.status == 200:
            # 响应状态码为200, 则提取响应中的数据并调用 store_data_in_database() 函数将数据存储到数据库中。
            data = response.json()
            self.store_data_in_database(data['data']['data'])
            # 在这里对获取的数据进行处理和提取
            # 可以使用data['key']来访问响应中的具体数据
        else:
            # 如果响应状态码不为 200,则记录错误日志。
            self.logger.error('Request failed with status code %s', response.status)

    def store_data_in_database(self, data):
        """
        将数据分别放在MySQL和HBase中
        :param data: 要存储的数据
        :return: 无返回值
        """
        # 连接到MySQL数据库
        # 导入pymysql包

        # 创建数据库连接
        conn = pymysql.connect(host="localhost", port=3306, user="root", passwd="root", db="data_analyze")
        cursor = conn.cursor()
        insert_query = "INSERT INTO hot_search (hot_content, search_link, ranking_time, highest_rank, duration, duration_number, search_index_peak, platform, date_number) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)"

        # 创建hbase数据库链接
        connection = happybase.Connection('192.168.139.136')
        # 选择要操作的表
        table_name = 'hot_search'
        table = connection.table(table_name)

        for item in data:
            hot_content = item['title']
            search_link = item['url']
            ranking_time = item['ranking_time']
            highest_rank = item['ranking_max']
            duration = item['duration']
            duration_number = self.convert_time_to_seconds(duration)
            search_index_peak = item['heats_max']
            numeric_value = round(float(search_index_peak[:-1]), 1)
            date_number = self.convert_date_to_number(ranking_time)
            platform = 4

            values = (hot_content, search_link, ranking_time, highest_rank, duration, duration_number, numeric_value, platform, date_number)
            print(values)
            cursor.execute(insert_query, values)

            # 存入hbase
            data = {
                'cf:hot_content': hot_content.encode(),
                'cf:search_link': search_link.encode(),
                'cf:ranking_time': ranking_time.encode(),
                'cf:highest_rank': str(highest_rank).encode(),
                'cf:duration': duration.encode(),
                'cf:duration_number': str(duration_number).encode(),
                'cf:search_index_peak': str(numeric_value).encode(),
                'cf:platform': str(platform).encode(),
                'cf:date_number': str(date_number).encode(),
            }
            unique_id = uuid.uuid4()  # 使用UUID来生成唯一的标识符
            row_key = str(unique_id)  # 将UUID转换为字符串作为行键
            table.put(row_key.encode(), data)

        # 提交更改并关闭连接
        conn.commit()
        conn.close()
        # 关闭hbase连接
        connection.close()

    def convert_time_to_seconds(self, time_input):
        """
        匹配等效时间为秒
        :param time_input: 时间字符串
        :return: 秒数
        """
        # 使用正则表达式匹配不同单位的时间值
        pattern = r'(\d+)\s*(天|小时|分|秒)?'
        matches = re.findall(pattern, time_input)

        # 定义时间单位与对应的秒数
        unit_seconds = {
            '天': 86400,
            '小时': 3600,
            '分': 60,
            '秒': 1
        }

        # 计算总的秒数
        total_seconds = 0

        for match in matches:
            value, unit = match
            value = int(value)

            if unit:
                total_seconds += value * unit_seconds[unit]

        return total_seconds
    def convert_date_to_number(self, time_date):
        """
        将日期转换为数字表示形式
        :param time_date: 日期字符串
        :return: 日期的数字表示形式
        """
        # 根据指定的日期时间格式解析字符串为日期时间对象
        datetime_obj = datetime.strptime(time_date, "%Y-%m-%d %H:%M")
        # 提取年、月、日部分
        year = datetime_obj.year
        month = datetime_obj.month
        day = datetime_obj.day

        # 将年、月、日转换为可比较的数字
        numeric_date = year * 10000 + month * 100 + day

        return numeric_date
